package com.hzy.alibaba.utils;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.*;

/***
 * @author huangzhaoyong
 * @desc CommonUtils 公共方法
 * @date 2018/7/11 14:54
 */
public class CommonUtils {

    public static <T> Map<String, List<T>> listToMapList(List<T> list, String key) throws Exception {
        return listToMapList(list, key, Lists.newArrayList());
    }

    public static <T> Map<String, List<T>> listToMapList(List<T> list, String key, List<String> valueList) throws Exception {
        Map<String, List<T>> result = new HashMap<>();
        if (null == list || StringUtils.isEmpty(key)) {
            return result;
        }
        List<T> tList;
        Class cls;
        Field[] fields;
        String value;
        Map map;
        for (T t : list) {
            tList = new ArrayList<>();

            if (t instanceof Map) {
                map = (Map) t;
                if (null == map.get(key)) {
                    continue;
                }
                value = map.get(key).toString();
                if (null != result.get(value)) {
                    tList = result.get(value);
                }

                if (map.keySet().contains(key) && null != map.get(key)) {
                    tList.add(t);
                }
                result.put(value, tList);
                valueList.add(value);
                continue;
            }

            cls = t.getClass();
            //得到所有属性
            fields = ArrayUtils.addAll(t.getClass().getSuperclass().getDeclaredFields(), cls.getDeclaredFields());
            for (Field field : fields) {
                //打开私有访问
                field.setAccessible(true);
                //获取属性
                String name = field.getName();
                if (!name.equals(key) || null == field.get(t)) {
                    continue;
                }
                value = field.get(t).toString();
                if (null != result.get(value)) {
                    tList = result.get(value);
                }
                tList.add(t);
                result.put(value, tList);
                valueList.add(value);
            }
        }
        return result;
    }

    public static <T> Map<String, T> listToMap(List<T> list, String key) throws Exception {
        return listToMap(list, key, Lists.newArrayList());
    }

    public static <T> Map<String, T> listToMap(List<T> list, String key, List<String> valueList) throws Exception {
        Map<String, T> result = new HashMap<>();
        if (null == list || StringUtils.isEmpty(key)) {
            return result;
        }
        Class cls;
        Field[] fields;
        String value;
        for (T t : list) {
            cls = t.getClass();

            if (t instanceof Map) {
                if (((Map) t).keySet().contains(key) && null != ((Map) t).get(key)) {
                    result.put(((Map) t).get(key).toString(), t);
                    valueList.add(((Map) t).get(key).toString());
                }
                continue;
            }
            //得到所有属性
            fields = ArrayUtils.addAll(t.getClass().getSuperclass().getDeclaredFields(), cls.getDeclaredFields());
            for (Field field : fields) {
                //打开私有访问
                field.setAccessible(true);
                //获取属性
                String name = field.getName();
                if (!name.equals(key) || null == field.get(t)) {
                    continue;
                }
                value = field.get(t).toString();
                result.put(value, t);
                valueList.add(value);
            }
        }
        return result;
    }

    /**
     * bean转换成map
     *
     * @param t
     * @return
     * @throws Exception
     */
    public static <T> Map<String, Object> beanToMap(T t) {
        Class cls = t.getClass();
        Field[] fields = ArrayUtils.addAll(t.getClass().getSuperclass().getDeclaredFields(), cls.getDeclaredFields());
        Map<String, Object> result = Maps.newHashMap();
        for (Field field : fields) {
            // 打开私有访问
            field.setAccessible(true);
            // 获取属性
            String name = field.getName();
            Object value = null;
            try {
                value = field.get(t);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            if (null == value || StringUtils.isBlank(value.toString())) {
                continue;
            }
            try {
                value = field.get(t).toString();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            result.put(name, value);
        }
        return result;
    }

    /**
     * <pre>
     *     List<UserBean> userBeans = userDao.queryUsers();
     *     List<UserDTO> userDTOs = BeanUtil.batchTransform(UserDTO.class, userBeans);
     * </pre>
     *
     */
    public static <T> List<T> batchTransform(final Class<T> clazz, List<? extends Object> srcList) throws IllegalAccessException, InstantiationException {
        if (CollectionUtils.isEmpty(srcList)) {
            return Collections.emptyList();
        }

        List<T> result = new ArrayList<>(srcList.size());
        for (Object srcObject : srcList) {
            result.add(transfrom(clazz, srcObject));
        }
        return result;
    }

    /**
     * 封装{ org.springframework.beans.BeanUtils.copyProperties}，惯用与直接将转换结果返回
     *
     * <pre>
     *      UserBean userBean = new UserBean("username");
     *      return BeanUtil.transform(UserDTO.class, userBean);
     * </pre>
     */
    public static <T> T transfrom(Class<T> clazz, Object src) throws InstantiationException, IllegalAccessException  {
        if (src == null) {
            return null;
        }
        T instance  = clazz.newInstance();
        BeanUtils.copyProperties(src, instance, getNullPropertyNames(src));
        return instance;
    }

    private static String[] getNullPropertyNames(Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<String>();
        for (PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) {
                emptyNames.add(pd.getName());
            }
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }

    /**
     * 设置cookie
     *
     * @param response
     * @param cookieName
     */
    public static String setCookieByParams(HttpServletResponse response, String cookieName) {
        String uuid = UUID.randomUUID().toString().replace("-", "").toLowerCase();
        Cookie cookie = new Cookie(cookieName, uuid);
        cookie.setPath("/");//不添加时，下面的request获取不到
        response.addCookie(cookie);
        return uuid;
    }

    /**
     * 获取cookie，并删除对应的值
     *
     * @param response
     * @param request
     * @param cookieName
     * @return
     */
    public static String getCookieByParams(HttpServletResponse response, HttpServletRequest request, String cookieName) {
        Cookie[] cookies = request.getCookies();
        if (null == cookies || cookies.length < 1) {
            return "";
        }
        String uuid = "";
        for (Cookie c : cookies) {
            if (!c.getName().equalsIgnoreCase(cookieName)) {
                continue;
            }
            uuid = c.getValue();
            //删除cookie
            c.setMaxAge(0);
            response.addCookie(c);
        }
        return uuid;
    }

    /**
     * 判断一个逗号分隔的字符串中是否包含某项元素
     *
     * @param commaSeparatedString
     * @param target
     * @return
     */
    public static boolean isContain(String commaSeparatedString, String target) {
        if (commaSeparatedString == null || target == null) {
            return false;
        }
        String[] items = commaSeparatedString.split(",");
        for (int i = 0; i < items.length; i++) {
            String item = items[i];
            if (StringUtils.equals(item, target)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 将集合拆分
     *
     * @param list
     * @param len
     * @param <T>
     * @return
     */
    public static <T> List<List<T>> getSubList(List<T> list, int len) {
        List<List<T>> listGroup = new ArrayList<List<T>>();
        if (list.size() < len) {
            listGroup.add(list);
            return listGroup;
        }
        int listSize = list.size();
        //子集合的长度
        int toIndex = len;
        for (int i = 0; i < list.size(); i += len) {
            if (i + len > listSize) {
                toIndex = listSize - i;
            }
            List<T> newList = list.subList(i, i + toIndex);
            listGroup.add(newList);
        }
        return listGroup;
    }

    /**
     * 模糊手机号
     *
     * @param phone
     * @return
     */
    public static String hiddenPhone(String phone) {
        String phoneNumber = phone.substring(0, 3) + "****" + phone.substring(7);
        return phoneNumber;
    }
}
